home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 242 / Issue 242 - April 2008 - DPCS0408DVD.ISO / Software Money Savers / VirtualDub / Source / VirtualDub-1.7.7-src.7z / src / h / vd2 / system / VDRingBuffer.h < prev    next >
Encoding:
C/C++ Source or Header  |  2007-10-13  |  6.1 KB  |  270 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    System library component
  3. //    Copyright (C) 1998-2004 Avery Lee, All Rights Reserved.
  4. //
  5. //    Beginning with 1.6.0, the VirtualDub system library is licensed
  6. //    differently than the remainder of VirtualDub.  This particular file is
  7. //    thus licensed as follows (the "zlib" license):
  8. //
  9. //    This software is provided 'as-is', without any express or implied
  10. //    warranty.  In no event will the authors be held liable for any
  11. //    damages arising from the use of this software.
  12. //
  13. //    Permission is granted to anyone to use this software for any purpose,
  14. //    including commercial applications, and to alter it and redistribute it
  15. //    freely, subject to the following restrictions:
  16. //
  17. //    1.    The origin of this software must not be misrepresented; you must
  18. //        not claim that you wrote the original software. If you use this
  19. //        software in a product, an acknowledgment in the product
  20. //        documentation would be appreciated but is not required.
  21. //    2.    Altered source versions must be plainly marked as such, and must
  22. //        not be misrepresented as being the original software.
  23. //    3.    This notice may not be removed or altered from any source
  24. //        distribution.
  25.  
  26. #ifndef f_SYSTEM_VDRINGBUFFER_H
  27. #define f_SYSTEM_VDRINGBUFFER_H
  28.  
  29. #include <string.h>
  30. #include <utility>
  31.  
  32. #include <vd2/system/atomic.h>
  33.  
  34. template<class T, class Allocator = std::allocator<T> >
  35. class VDRingBuffer : private Allocator {
  36. protected:
  37.     T                *pBuffer;
  38.     int                 nSize;
  39.     int                 nReadPoint;
  40.     int                 nWritePoint;
  41.     VDAtomicInt         nLevel;
  42.  
  43. public:
  44.     VDRingBuffer();
  45.     VDRingBuffer(int size);
  46.     ~VDRingBuffer();
  47.  
  48.     void     Init(int size);
  49.     void     Shutdown();
  50.  
  51.     int         getSize() const { return nSize; }
  52.     int         getLevel() const { return nLevel; }
  53.     int         getSpace() const { return nSize - nLevel; }
  54.     int         getReadOffset() const { return nReadPoint; }
  55.     int         getWriteOffset() const { return nWritePoint; }
  56.     int         getWriteSpace() const;
  57.     T *         getWritePtr() const { return pBuffer+nWritePoint; }
  58.  
  59.     bool     empty() const { return !nLevel; }
  60.     bool     full() const { return nLevel == nSize; }
  61.  
  62.     void     Flush() { nReadPoint = nWritePoint = nLevel = 0; }
  63.  
  64.     int         Read(T *pBuffer, int bytes);
  65.     const T    *LockRead(int requested, int& actual);
  66.     const T *LockReadWrapped(int requested, int& actual, int& nReadPoint);
  67.     int         UnlockRead(int actual);
  68.  
  69.     int         Write(const T *pData, int bytes);
  70.     T        *LockWrite(int requested, int& actual);
  71.     T        *LockWriteAll(int& actual);
  72.     int         UnlockWrite(int actual);
  73. };
  74.  
  75. template<class T, class Allocator>
  76. VDRingBuffer<T, Allocator>::VDRingBuffer(int size)
  77. : pBuffer(0)
  78. {
  79.     Init(size);
  80. }
  81.  
  82. template<class T, class Allocator>
  83. VDRingBuffer<T, Allocator>::VDRingBuffer()
  84. : nSize(0)
  85. , nLevel(0)
  86. , nReadPoint(0)
  87. , nWritePoint(0)
  88. , pBuffer(0)
  89. {
  90. }
  91.  
  92. template<class T, class Allocator>
  93. VDRingBuffer<T, Allocator>::~VDRingBuffer() {
  94.     Shutdown();
  95. }
  96.  
  97. template<class T, class Allocator>
  98. void VDRingBuffer<T, Allocator>::Init(int size) {
  99.     Shutdown();
  100.     pBuffer        = allocate(nSize = size, 0);
  101.     nLevel        = 0;
  102.     nReadPoint    = 0;
  103.     nWritePoint    = 0;
  104. }
  105.  
  106. template<class T, class Allocator>
  107. void VDRingBuffer<T, Allocator>::Shutdown() {
  108.     if (pBuffer) {
  109.         deallocate(pBuffer, nSize);
  110.         pBuffer = NULL;
  111.     }
  112. }
  113.  
  114. template<class T, class Allocator>
  115. int VDRingBuffer<T, Allocator>::getWriteSpace() const {
  116.     volatile int tc = nSize - nWritePoint;
  117.     volatile int space = nSize - nLevel;
  118.  
  119.     if (tc > space)
  120.         tc = space;
  121.  
  122.     return tc;
  123. }
  124.  
  125. template<class T, class Allocator>
  126. int VDRingBuffer<T, Allocator>::Read(T *pBuffer, int units) {
  127.     VDASSERT(units >= 0);
  128.  
  129.     int actual = 0;
  130.     const T *pSrc;
  131.  
  132.     while(units) {
  133.         int tc;
  134.  
  135.         pSrc = LockRead(units, tc);
  136.  
  137.         if (!tc)
  138.             break;
  139.  
  140.         memcpy(pBuffer, pSrc, tc * sizeof(T));
  141.  
  142.         UnlockRead(tc);
  143.  
  144.         actual += tc;
  145.         units -= tc;
  146.         pBuffer += tc;
  147.     }
  148.  
  149.     return actual;
  150. }
  151.  
  152. template<class T, class Allocator>
  153. const T *VDRingBuffer<T, Allocator>::LockRead(int requested, int& actual) {
  154.     VDASSERT(requested >= 0);
  155.  
  156.     int nLevelNow = nLevel;
  157.  
  158.     if (requested > nLevelNow)
  159.         requested = nLevelNow;
  160.  
  161.     if (requested + nReadPoint > nSize)
  162.         requested = nSize - nReadPoint;
  163.  
  164.     actual = requested;
  165.  
  166.     return pBuffer + nReadPoint;
  167. }
  168.  
  169. template<class T, class Allocator>
  170. const T *VDRingBuffer<T, Allocator>::LockReadWrapped(int requested, int& actual, int& readpt) {
  171.     int nLevelNow = nLevel;
  172.  
  173.     if (requested > nLevelNow)
  174.         requested = nLevelNow;
  175.  
  176.     actual = requested;
  177.     readpt = nReadPoint;
  178.  
  179.     return pBuffer;
  180. }
  181.  
  182. template<class T, class Allocator>
  183. int VDRingBuffer<T, Allocator>::UnlockRead(int actual) {
  184.     VDASSERT(actual >= 0);
  185.     VDASSERT(nLevel >= actual);
  186.  
  187.     int newpt = nReadPoint + actual;
  188.  
  189.     if (newpt >= nSize)
  190.         newpt -= nSize;
  191.  
  192.     nReadPoint = newpt;
  193.  
  194.     return nLevel.add(-actual);
  195. }
  196.  
  197. template<class T, class Allocator>
  198. int VDRingBuffer<T, Allocator>::Write(const T *pData, int bytes) {
  199.     VDASSERT(bytes >= 0);
  200.  
  201.     int actual = 0;
  202.     void *pDst;
  203.  
  204.     while(bytes) {
  205.         int tc;
  206.  
  207.         pDst = LockWrite(bytes, tc);
  208.  
  209.         if (!actual)
  210.             break;
  211.  
  212.         memcpy(pDst, pBuffer, tc);
  213.  
  214.         UnlockWrite(tc);
  215.  
  216.         actual += tc;
  217.         bytes -= tc;
  218.         pBuffer = (char *)pBuffer + tc;
  219.     }
  220.  
  221.     return actual;
  222. }
  223.  
  224. template<class T, class Allocator>
  225. T *VDRingBuffer<T, Allocator>::LockWrite(int requested, int& actual) {
  226.     VDASSERT(requested >= 0);
  227.     int nLevelNow = nSize - nLevel;
  228.  
  229.     if (requested > nLevelNow)
  230.         requested = nLevelNow;
  231.  
  232.     if (requested + nWritePoint > nSize)
  233.         requested = nSize - nWritePoint;
  234.  
  235.     actual = requested;
  236.  
  237.     return pBuffer + nWritePoint;
  238. }
  239.  
  240. template<class T, class Allocator>
  241. T *VDRingBuffer<T, Allocator>::LockWriteAll(int& actual) {
  242.     int requested = nSize - nLevel;
  243.  
  244.     if (requested + nWritePoint > nSize)
  245.         requested = nSize - nWritePoint;
  246.  
  247.     actual = requested;
  248.  
  249.     return pBuffer + nWritePoint;
  250. }
  251.  
  252. template<class T, class Allocator>
  253. int VDRingBuffer<T, Allocator>::UnlockWrite(int actual) {
  254.     VDASSERT(actual >= 0);
  255.     VDASSERT(nLevel + actual <= nSize);
  256.  
  257.     int newpt = nWritePoint + actual;
  258.  
  259.     if (newpt >= nSize)
  260.         newpt = 0;
  261.  
  262.     nWritePoint = newpt;
  263.  
  264.     return nLevel.add(actual);
  265. }
  266.  
  267.  
  268.  
  269. #endif
  270.